SQS / SNSのローカル実装 CMB (Cloud Message Bus) を試してみた
よく訓練されたアップル信者、都元です。Amazon SQS及びSNSは、AWSにおけるスケーラブルでマネージド、そして格安のメッセージングサービスです。これらのプロダクトは「サービス」であり、開発サーバやローカルマシンにインストールして使うものではありません。
しかし、テストや開発目的で、ローカルで動作させたいこともあるかもしれません。ちなみにDynamoDBも同じようなサービスですが、こちらは公式にDynamoDB Local等のソリューションが存在します。
残念ながら、SQSやSNSにはこのような公式の対応がありませんが、GitHubをウロウロしていたら CMB (Cloud Message Bus)という、SQS/SNS互換実装が見つかったので、さっと試してみました。
インストール
CMB本体のインストール
まずはダウンロード。配布ページがあったので、こちらからダウンロードします。本検証では執筆時点の最新版「Version 2.2.43」を利用しました。インストール先はローカルのMac OSXです。
$ cd workdir $ wget http://cmb-releases.s3-website-us-west-1.amazonaws.com/2.2.43/cmb-distribution-2.2.43.tar.gz $ tar xzvf cmb-distribution-*.tar.gz
とりあえずはダウンロードして展開するだけ。cmbというディレクトリが掘られ、そこに全てのファイルが展開されます。cmb/config/cmb.propertiesが設定ファイルなので、中を覗いてみましょう。
cmb.cqs.service.url=http://localhost:6059/ cmb.cns.service.url=http://localhost:6061/
これらがローカルでのエンドポイントになります。
# # configure email relay here, if email protocol is desired for cns, otherwise set enabled to false # cmb.cns.smtp.enabled=false cmb.cns.smtp.hostname= cmb.cns.smtp.username= cmb.cns.smtp.password= cmb.cns.smtp.replyAddress=
また、SNSにおいてemailやemail-jsonのsubscriptionを利用する場合、メールサーバの設定が必要です。残念ながら私の環境でさっと設定できるメールサーバを用意できなかったので、メールの配信までは本稿で検証できていません。設定出来る方はしておきましょう。
他はデフォルトのままで上手く動きました。
CassandraとRedisのインストール
CMBは裏側でCassandraとRedisを利用しています。…本格的じゃないですか。ローカル用の仮実装というイメージからはちょっと離れてしまいますねぇ、というのが本音ですが。まぁGitHub上のrepository descriptionも「A highly available, horizontally scalable queuing and notification service compatible with AWS SQS and SNS」となっていて。高可用性とスケーラビリティを謳ってます。いや、仮実装でいいからもっとライトなの探したほうがいいんすかね。
ま、いいです。とりあえずCassandraとRedisをインストールしましょう。私の環境にはまだインストールされていなかったのでhomebrewでサクッと入れました。
Cassandra
Cassandraはv2系が出ているようですが、ドキュメントに2.0のスキーマ定義がなかったので、1.2を選択。
$ brew install cassandra12 $ brew info cassandra12 cassandra12: stable 1.2.19 $ ln -sfv /usr/local/opt/cassandra12/*.plist ~/Library/LaunchAgents $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.cassandra12.plist
言われるがまま、launchctlの設定も済ませました。
$ cassandra-cli -h localhost -f cmb/schema/cassandra_1.2.schema
そして上記コマンドでスキーマの作成を行います。UUIDっぽいのがズラズラと出てくれば多分成功です。
ちなみに私は起動時にError: Could not find or load main class org.apache.cassandra.cli.CliMainというエラーにぶつかりました。その昔、cassandra-0.7.9をインストールしていたようで、環境変数CASSANDRA_HOMEがv0.7.9を指していました。ご参考に。
そしてもうひとつ。キースペースCNSが見つからん、というエラーでも落ちました。cmb/schema/cassandra_1.2.schemaを覗いてみると、先頭にdrop keyspace文が3つ並んでいます。こうすべきなのかはよくわかりませんが、この3つをコメントアウトしたら上手く動きました。
Redis
$ brew install redis $ brew info redis redis: stable 2.8.19 (bottled), HEAD
設定ファイル/usr/local/etc/redis.confを一部編集します。下記の3行を#でコメントアウトしましょう。
save 900 1 save 300 10 save 60 10000
そしてredis-server /usr/local/etc/redis.confコマンドでコンソール起動。
起動と設定
以上で動作環境は整いました。sudo cmb/bin/cmb.shでCMB起動です。sudoが無いと動きませんでした。なぜかは追ってません。
起動したら http://localhost:6059/webui にアクセスしてみてください。
初期ログインは、username/password共にcns_internalです。
ログインすると、ユーザの管理画面になります。アクセスキーとシークレットが見えますので控えておきましょう。
表の中のCNS(SNSのCMB実装)をクリックするとこのようにtopic管理画面になりますので、適当にトピック名を入力して作成してみます。
できました。
続いて(メールは届きませんが)subscribeしてみましょう。
簡単ですね。SNS (CNS)はこのあたりで。引き続き、CQS(SQSのCMB実装)の方も見てみましょう。
既に5つのキューがありましたが、6つ目を作ってみました。ちなみにこの表は横に長くてですね。。。
AttributeやPurgeにも対応していました。
AWS SDK for Javaから使ってみる
// CNS (SNS) の利用準備 AmazonSNS sns = new AmazonSNSClient(creds); sns.setEndpoint("http://localhost:6061/"); // CNSにpublish sns.publish("arn:cmb:cns:eu-west-1:424143290207:cmsample", "Hello, CNS!"); // CQS (SQS) の利用準備 AmazonSQS sqs = new AmazonSQSClient(creds); sqs.setEndpoint("http://localhost:6059/"); // CQSにsend SendMessageResult result = sqs.sendMessage("http://localhost:6059/424143290207/cmsamplequeue", "Hello, CQS!"); System.out.println("MessageId = " + result.getMessageId()); System.out.println("MD5OfMessageBody = " + result.getMD5OfMessageBody()); System.out.println("MD5OfMessageAttributes = " + result.getMD5OfMessageAttributes()); // CQSからread ReceiveMessageResult receiveMessage = sqs.receiveMessage("http://localhost:6059/424143290207/cmsamplequeue"); receiveMessage.getMessages().stream().map(msg -> msg.getBody()).forEach(System.out::println);
なんてことはありませんね。setEndpointで、ローカルを指してやるだけで、動きました。
MessageId = 0:0:0_0_81:2986657831232471042:-5491847274831020032 MD5OfMessageBody = 1b51da5780bbd08ce96081f7b6ba4983 MD5OfMessageAttributes = null Hello, CQS!
残念ながら、SNSのメッセージの受信確認はできませんでしたが、普通に受信できるものだと思います。
最後に
一応、ドキュメントに明示されていた制限事項を確認しておきましょう。
- AWS SDK for Java v1.9.14 を使って動作確認をしています。(意外と最新に近いですね)
- Cassandra 1.0.10 では動きません。1.1.X, 2.0.X, 2.1.XはOK(2.0で動くんじゃないか。。。)
- CNSはSMSプロトコルはサポートしません。
- CNSはスロットルポリシーをサポートしません。
- CNSはモバイルpushをサポートしません。
- CQNはDLQをサポートしません。
とのことです。この制限の中では便利に使えるのではないでしょうか。